﻿package fwk.siteManager2 {	
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import fwk.siteManager2.BO.RessourceGroupData;
	import fwk.siteManager2.BO.DisplayElementData;
	import fwk.siteManager2.BO.PageData;
	import fwk.siteManager2.BO.RessourceData;
	import fwk.siteManager2.interfaces.ITemplate;
	
	import fwk.siteManager2.events.TemplateEvent;
	import fwk.siteManager2.events.SiteManagerEvent;
	import fwk.loaderManager.LoaderItemGroup;
	import fwk.loaderManager.LoaderItemObject;
	
	import flash.net.getClassByAlias;
	
//	import fwk.interfaces.IPage;
	

	/**
	 * Cette classe représente un template de page composé d'une liste de ressources de tous type accessibles.
	 * Vous ne devez pas instancier cette classe vous même. Si vous faites votre propre template, votre classe doit hérité de celle ci pour pouvoir être géré par MainBase.
	 * Si une ressource est de type DisplayElement, elle est ajouté à la liste d'affichage du template et est controlé par le template (appel des méthode init, display, close, etc...).
	 * 
	 */
	public class Template extends Sprite implements ITemplate
	{
		
		///////////////////////////
		// private properties
		private var _uiRessource:String = "";
		private var _uipage:String 		= "";
		private var _pageData:PageData;
		private var _ressourceGroupData:RessourceGroupData;
		
		private var _initialized:Boolean = false;
		private var _deepLink:String;
		private var _ressources:Object; 					// contient les ressources du template
		
		private var _tabDisplayElements:Array;
		private var _nbElementClosed:Number = 0;
		
		private var _cache:Boolean = false;
		
		/**
		 * Renvoie un tableau contenant les DisplayElements affiché dans le template de page
		 */
		public function get tabDisplayElements():Array
		{
			return _tabDisplayElements;
		}
		/**
		 * Renvoie le noeud xml se trouvant dans le xml templates correspondant à la page
		 */
		public function get xmlPage():XML
		{
			return _pageData.xmlDescription;
		}
		/**
		 * Renvoie le noeud xml se trouvant dans le xml templates correspondant à la ressource associé à la page
		 */
		public function get xmlRessource():XML
		{
			return _ressourceGroupData.xmlDescription;
		}
		public function get deepLink():String
		{
			return _deepLink;
		}
		public function set deepLink(val:String):void
		{
			App.mainClass.deepLink = val;
		}
		/**
		 * Renvoie l'identifiant de la page
		 */
		public function get uipage():String
		{
			return _uipage;
		}
		public function set uipage(val:String):void
		{
			_uipage = val;
		}
		/**
		 * Renvoie l'identifiant de la ressource associé à la page
		 */
		public function get uiRessource():String
		{
			return _uiRessource;
		}
		public function set uiRessource(val:String):void
		{
			_uiRessource = val;
		}
		/**
		 * Renvoie un Object contenant les ressources chargées de la page. Exemple ressources["xmlPage1"] (renvoie une String) ou xmlPage1 correspond à l'id de la ressource déclaré dans le noeud de la page en cours
		 */
		public function get ressources():Object
		{
			return _ressources;
		}
		public function get initialized():Boolean
		{
			return _initialized;
		}
		
		public function get pageData():PageData { return _pageData; }
		
		public function set pageData(value:PageData):void 
		{
			_pageData = value;
		}
		
		public function get ressourceGroupDate():RessourceGroupData { return _ressourceGroupData; }
		
		public function set ressourceGroupDate(value:RessourceGroupData):void 
		{
			_ressourceGroupData = value;
		}
		//-----------------------------------------------------------------------
		// Constructeur
		//-----------------------------------------------------------------------
		function Template ()
		{
			
			pageData = new PageData();
			_ressourceGroupData = new RessourceGroupData();
			
		}
		
		//-----------------------------------------------------------------------
		// Methodes
		//-----------------------------------------------------------------------
		public final function _init():void
		{
			if (!_initialized)
			{
				
				_tabDisplayElements = new Array();
				
				_uipage 		= _pageData.id;
				
				App.mainClass.debugIt("--------> Template " + _uipage + " .init()");
				
				this.x 			= _pageData.x;
				this.y 			= _pageData.y;

				_deepLink = App.mainClass.deepLink;
					
				
				// init des ressources pages
				_ressources = new Object();

				var resData:RessourceData;
				var element:Object;
				var k:int;

				var ressourcePage:LoaderItemGroup = App.mainClass.getLoaderItemPage(_uipage) as LoaderItemGroup;
				if (_pageData != null && ressourcePage != null)
				{
					for (k = 0; k < _pageData.listRessources.length; k++)
					{
						addRessource(_pageData.listRessources[k] as RessourceData);
					}
					
					// dynamics displayElement
					for (k = 0; k < _pageData.listDynamicDisplayElement.length; k++)
					{
						
						
						var dDate:DisplayElementData = _pageData.listDynamicDisplayElement[k];
						
						var cl:Class = getClassByAlias( dDate.classAlias ) as Class;
						var dElement:DisplayElement = new cl() as DisplayElement;
						
						dElement._init(dDate.id);
						dElement.addEventListener(TemplateEvent.CLOSED, onCloseElementFinish);
						dElement.template = this;
						_tabDisplayElements.push(dElement);
						
						dElement.x = dDate.x;
						dElement.y = dDate.y;
						
						if (dDate.display)
						{
							this.addChild(dElement as DisplayObject);
							if (dDate.center) {
								dElement.x = App.mainClass.width/2 - dElement.width/2;
								dElement.y = App.mainClass.height/2 - dElement.height/2;
							}
						}

					}

				}
				
				// uiRessources
				if (_ressourceGroupData != null)
				{
					_uiRessource 	= _ressourceGroupData.id;
					ressourcePage = App.mainClass.getLoaderItemRessource(_uiRessource) as LoaderItemGroup;

					for (k = 0; k < _ressourceGroupData.listRessources.length; k++) {
						addRessource(_ressourceGroupData.listRessources[k] as RessourceData);
					}

				}
				
				function addRessource($resData:RessourceData):void
				{
					
						resData = $resData;
						
						if (ressourcePage.tabItem[resData.id] != null)
						{

							element = (ressourcePage.tabItem[resData.id] as LoaderItemObject).content;
							_ressources[resData.id] = element;
							if (element is DisplayObject)
							{
								element.x = resData.x;
								element.y = resData.y;
									
								
								if (resData.display)
								{
									this.addChild(element as DisplayObject);
									if (resData.center) {
										element.x = App.mainClass.width/2 - element.width/2;
										element.y = App.mainClass.height/2 - element.height/2;
									}
								}
							}
							
							/*if (element is DisplayElement && App.mainClass.xmlContentPage == null)
							{
								
								element._init(resData.id, resData.xmlDescription);
								element.addEventListener(TemplateEvent.CLOSED, onCloseElementFinish);
								element.template = this;
								_tabDisplayElements.push(element);
								
							}*/
					
						}
				}
					
				
				_initialized = true;
				
				dispatchEvent(new TemplateEvent(TemplateEvent.ON_READY));
				
			}
			
			// init elements
			for (var i:int = 0; i < tabDisplayElements.length; i++)
			{
				_tabDisplayElements[i].init();
			}
			init();
		}
		public final function onContextChange(evt:SiteManagerEvent):void
		{
			
			var tab:Array = evt.deepLink.split(App.mainClass.splitDeepLink);

			
			if ( tab[1] == uipage) {
				//App.mainClass.debugIt("---------- onContextChange template ---------- " + evt.deepLink);
				

				_deepLink = evt.deepLink;
				onDeepLinkChange();
			}
			

			
		}
		/**
		 * Initilise la page. Appelé une seule fois par instance. Cette méthode est appelé par MainBase automatiquement quand une nouvelle page est créé et affichée. Vous pouvez redefinir cette méthode pour initialisé ce qui est spécifique à votre page.
		 */
		public function init():void
		{
				
			
		}
		public final function _display():void
		{
			App.mainClass.debugIt("--------> Template " + _uipage + " .display()");	
			
			// ajout ecouteur context change
			App.mainClass.addEventListener(SiteManagerEvent.CONTEXT_CHANGE, onContextChange);
			
			if (_tabDisplayElements.length > 0)
			{
				_nbElementClosed = 0;
				for (var i:int = 0; i < tabDisplayElements.length; i++)
				{
					(_tabDisplayElements[i] as DisplayElement).display();
					(_tabDisplayElements[i] as DisplayElement).visible = true;
				}
			}
			
			display();
			
		}
		/**
		 * Lance l'animation d'ouverture de la page. Cette méthode est appelé par MainBase automatiquement quand une page est affichée. Vous pouvez redefinir cette méthode pour effectuer votre propre animation.
		 */
		public function display():void
		{
			
			
			if (_tabDisplayElements.length == 0){
				this.alpha = 0;
				
				App.mainClass.containerLoader.stage.addEventListener(Event.ENTER_FRAME, onEnterFrameAnimDisplay);
				function onEnterFrameAnimDisplay(evt:Event):void
				{
					alpha += 0.1;
					
					if ( alpha >= 1) {
						App.mainClass.containerLoader.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrameAnimDisplay);
						onDisplayFinish();
					}
					
				}
				
				
			}
			
		}
		
		
		/**
		 * Lance l'animation de fermeture de la page. Cette méthode est appelé par MainBase automatiquement quand une page nouvelle page doit être affichée. Vous pouvez redefinir cette méthode pour effectuer votre propre animation.
		 * Ne pas oublier d'appeler la méthode onCloseFinish quand votre animation est fini pour avertir MainBase que l'animation est fini.
		 */
		public function close():void
		{
			App.mainClass.debugIt("--------> Template " + _uipage + " .close()");
			
			_nbElementClosed = 0;
			
			if (_tabDisplayElements.length > 0)
			{
				for (var i:int = 0; _tabDisplayElements != null && i < _tabDisplayElements.length; i++)
				{
					(_tabDisplayElements[i] as DisplayElement).close();
				}
			}else
			{
				
				App.mainClass.containerLoader.stage.addEventListener(Event.ENTER_FRAME, onEnterFrameAnimClose);
				function onEnterFrameAnimClose(evt:Event):void
				{
					alpha -= 0.1;
					
					if ( alpha <= 0) {
						App.mainClass.containerLoader.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrameAnimClose);
						onCloseFinish();
					}
					
				}
			}	

		}
		public function onCloseElementFinish(evt:TemplateEvent):void
		{
			_nbElementClosed++;
			
			//App.mainClass.debugIt("onCloseElementFinish " + _nbElementClosed);
			
			if (_tabDisplayElements.length == _nbElementClosed)
			{
				onCloseFinish();
			}
			
		}


		public final function onDisplayFinish():void
		{
			//App.mainClass.debugIt("---------- onDisplayFinish Page ----------");

			dispatchEvent(new TemplateEvent(TemplateEvent.FINISHED));
		}
		/**
		 * Appelé cette méthode pour avertir que l'animation de fermeture de page est fini.
		 * note : Elle est automatiquement appelé si vous utilisé la méthode de base close
		 */
		public function onCloseFinish():void
		{
			//App.mainClass.debugIt("---------- onCloseFinish Page ----------");
			
			// retire ecouteur context change
			App.mainClass.removeEventListener(SiteManagerEvent.CONTEXT_CHANGE, onContextChange);
			
			if( !_cache) _initialized = false;
			
			this.alpha = 1;
			dispatchEvent(new TemplateEvent(TemplateEvent.CLOSED));
		}
		/**
		 * Pour tuer la classe (vider la mémoire etc...)
		 */
		public function dispose():void
		{
			
			if( !_cache )
			{
				for(var p:String in _ressources)
				{
					if( (_ressources[p] as DisplayObject) != null){
						var disp:DisplayObject = _ressources[p];
						if( disp.parent != null && !(disp.parent is Loader)){
							disp.parent.removeChild(disp);
						}
						
					}
		
				}
				
				for (var i:int = 0; i < _tabDisplayElements.length; i++)
				{
					var element:DisplayElement = (_tabDisplayElements[i] as DisplayElement);
					element.removeEventListener(TemplateEvent.CLOSED, onCloseElementFinish);
					element.dispose();
					if( element.parent != null && !(element.parent is Loader)){
						element.parent.removeChild(element);
					}
				}
				_pageData = null;
				_tabDisplayElements = null;
				
	
				_ressources 		= null;
				_ressourceGroupData = null;
			}
			


			
		}
		/**
		 * Cette méthode est déclanché automatiquement dés qu'il y a un changement de deepLink. Vous pouvez la redefinir pour effectuer les actions que vous voulez.
		 */
		public function onDeepLinkChange():void
		{
			for (var i:int = 0; i < _tabDisplayElements.length; i++)
			{
				(_tabDisplayElements[i] as DisplayElement).onDeepLinkChange();
			}
		}
		
		public function get cache() : Boolean {
			return _cache;
		}
		
		public function set cache(cache : Boolean) : void {
			_cache = cache;
		}
	}
}